package com.astrob.activitys;

import android.annotation.SuppressLint;
import android.content.Context;

import com.astrob.NavFrameSDK;
import com.astrob.NavFrameSDK.NavPosition;
import com.astrob.activitys.GPSProvider.NetPosCallBack;
import com.astrob.model.GeoHash;
import com.astrob.model.LonLat;
import com.astrob.naviframe.Start;
import com.astrob.util.SysUtils;
import com.nhc.database.dbmodel.TrackPoint;
import com.nhc.database.manager.QiyaCenter;
import com.nhc.model.TripDataFileHandle;

import java.util.Timer;
import java.util.TimerTask;

public class PositionProvider implements NetPosCallBack {

    private static PositionProvider instance = new PositionProvider();

    public static PositionProvider getInstance() {
        return instance;
    }

    public interface PosCallBack {
        // 刷新位置
        void updatePos(NavPosition navpos, boolean isNetPos);
    }

    public PosCallBack mCallback = null;

    private Timer mTimer = null;

    public static final int PATHSIMU_PROVIDER = 0;
    public static final int GPS_PROVIDER = 1;
    public static final int NMEALOG_PROVIDER = 2;
    private static int mProvider = GPS_PROVIDER;

    public NavPosition mNavpos = null;
    private GPSProvider mGpsProvider = null;

    private boolean mHaveNMEALog = false;
    Context mContext;

    public void init(Context context, PosCallBack callback) {
        mCallback = callback;

        // timer只需启动一次
        if (mContext != null) {
            return;
        }

        if (mNavpos == null) {
            mNavpos = NavFrameSDK.getInstance().new NavPosition();
        }

        mContext = context;

        mHaveNMEALog = NMEALogProvider.getInstance().haveNMEALog();

        if (mGpsProvider == null) {
            mGpsProvider = GPSProvider.getInstance();
            mGpsProvider.mHaveNMEALog = mHaveNMEALog;
            mGpsProvider.mNetCallback = this;
            mGpsProvider.initGPSProvider(mContext);
        }

        setProviderMode(GPS_PROVIDER);

    }

    public void setProviderMode(int provider) {
        if (mHaveNMEALog && provider == GPS_PROVIDER) {
            mProvider = NMEALOG_PROVIDER;
        } else {
            mProvider = provider;
        }
        begin();
    }

    public int getProviderMode() {
        return mProvider;
    }

    public void begin() {
        end();

        int timerInterval = 500;
        mSimuStep = 1;
        switch (mProvider) {
            case PATHSIMU_PROVIDER:
                Start.getInstance().MapKit().initPathSimu();
                if (Start.getInstance().MapKit().mNavStart.pos.lon == 0) {
                    if (Start.getInstance().MapKit().getNextSimuData(mNavpos, 1)) {
                        Start.getInstance().MapKit().mNavStart.pos = mNavpos.pos;
                    }
                }
                break;
            case GPS_PROVIDER:
                timerInterval = 1000;
                break;
            case NMEALOG_PROVIDER:
                timerInterval = 1000;
                break;
        }

        mTimer = new Timer();
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                sendpos();
            }
        }, 1, timerInterval);
    }

    public void end() {
        killTimer(mTimer);
    }

    private void killTimer(Timer timer) {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

    private int mSimuStep = 4; // 1 2 4 8
    private int SIMUSPEED[] = {40, 80, 160, 300};

    public int setSimuStep(boolean needAdd) {
        if (needAdd) {
            mSimuStep = mSimuStep * 2;
        } else {
            mSimuStep = mSimuStep / 2;
        }

        if (mSimuStep > 8) {
            mSimuStep = 1;
        }

        return mSimuStep;
    }

    private boolean mSimuCloseDest = false;

    public void setSimuCloseDest(boolean simuCloseDest) {
        mSimuCloseDest = simuCloseDest;
    }

    public void sendpos() {
        switch (mProvider) {
            case PATHSIMU_PROVIDER:
                int simuStep = mSimuStep;
                if (mSimuCloseDest) {
                    simuStep = 1;
                }
                if (!Start.getInstance().MapKit()
                        .getNextSimuData(mNavpos, simuStep)) {
                    return;
                }
                mNavpos.signal = 6;
                switch (simuStep) {
                    default:
                    case 1:
                        mNavpos.vel = SIMUSPEED[0];
                        break;
                    case 2:
                        mNavpos.vel = SIMUSPEED[1];
                        break;
                    case 4:
                        mNavpos.vel = SIMUSPEED[2];
                        break;
                    case 8:
                        mNavpos.vel = SIMUSPEED[3];
                        break;
                }
                break;
            case GPS_PROVIDER:
                if (!getGPSData()) {
                    if (mCallback != null) {
                        mCallback.updatePos(null, false);//每秒刷一次
                    }
                    return;
                }
                break;
            case NMEALOG_PROVIDER: {
                if (!NMEALogProvider.getInstance().getNextData(mNavpos))
                    return;

                long datetime = System.currentTimeMillis();
                LonLat ll = new LonLat(mNavpos.pos.lon, mNavpos.pos.lat);
                if (ll.IsValid()) {

                    SysUtils.getInstance().saveLL(ll);

                    double alt = NMEALogProvider.getInstance()._alt;
                    TrackPoint trackPoint = new TrackPoint(null, mNavpos.pos.lon, mNavpos.pos.lat, alt,
                            mNavpos.vel, mNavpos.dir, mNavpos.signal, datetime, 0L, "", "");
                    SysUtils.getInstance().saveTrackPoint(trackPoint);

                    TripDataFileHandle.getInstance().mTripDatainfo.addTotaltime();
                }

                if (mNavpos.signal == 0) {
                    if (!mFirstgps) {
                        mNavpos.vel = 20;
                        mFirstgps = true;
                    }
                }
            }
                break;
        }

        if (mCallback != null) {
            mCallback.updatePos(mNavpos, false);
        }
    }

    public int getGPSNumBmpPath() {
        if (mGpsProvider == null) {
            return 0;
        }
        int resid = 0;
        int num = mGpsProvider.getGPSNum();

        if (num > 9) {
            num = 9;
        }
        resid = resid + num;

        return resid;
    }

    public boolean isGPSFixed() {
        if (mGpsProvider == null) {
            return false;
        }
        return mGpsProvider.isFixed();
    }

    // 是否已经初次定位
    private boolean mFirstgps = false;
    int traceNum = 0;


    @SuppressLint("SimpleDateFormat")
    public boolean getGPSData() {
        NavPosition navpos = NavFrameSDK.getInstance().new NavPosition();
        if (mGpsProvider == null || !mGpsProvider.isFixed()) {
            return false;
        }

        LonLat pos = mGpsProvider.getPos();
        if (pos == null || pos.IsInvalid()) {
            navpos.signal = 100;
            navpos.vel = 0;
            return false;
        }

        navpos.pos.lon = pos.GetLon();
        navpos.pos.lat = pos.GetLat();
        navpos.dir = mGpsProvider.getDirection();
        navpos.vel = mGpsProvider.getSpeed() * 3.6; // km/h
        navpos.signal = (int) mGpsProvider.getAccuracy();

        mNavpos = navpos;

        TripDataFileHandle.getInstance().mTripDatainfo.addTotaltime();

        return true;
    }

    // 网络定位仅一次
    LonLat _netPos;

    @Override
    public void updateNetPos(LonLat netPos) {
        if (_netPos != null) {
            return;
        }
        _netPos = netPos;
        NavPosition navpos = NavFrameSDK.getInstance().new NavPosition();
        navpos.pos.lon = netPos.GetLon();
        navpos.pos.lat = netPos.GetLat();
        navpos.signal = 10;
        mNavpos = navpos;
        if (mCallback != null) {
            mCallback.updatePos(navpos, true);
        }
    }
}
